/**
 *
 */
package coms6111.astbbw.unitTest;

import static org.junit.Assert.*;

import java.util.*;

import org.junit.BeforeClass;
import org.junit.Test;

import coms6111.astbbw.webdb.DocumentSample;
import coms6111.astbbw.*;

/**
 * @author ben
 *
 */
public class DocumentSampleTest {
	private static TestableDocumentSample p, c;
	private static TreeSet<String> termsets[];
	private static String documents[][] = {
			{ "repeat", "repeat","page0only","everywhere" },
			{"page1only", "parent and child","everywhere"},
			{"page2only","everywhere"},
			{"page3only","everywhere"},
			{"page4only","everywhere"},
			{"page5only","everywhere"},
			{"page6only","everywhere"},
			{"page7only","everywhere"},
			{"page8only","parent and child","everywhere"},
			{"page9only","everywhere"}
	};
	/**
	 * @throws java.lang.Exception
	 */
	@SuppressWarnings("unchecked")
	@BeforeClass
	public static void setUpBeforeClass() throws Exception {
		org.apache.log4j.BasicConfigurator.configure();
		org.apache.log4j.Logger.getRootLogger().setLevel(org.apache.log4j.Level.OFF);
		p = new TestableDocumentSample();
		c = new TestableDocumentSample(p);
		termsets = new TreeSet[10];
		for (int i = 0; i < termsets.length; i++) {
			termsets[i] = new TreeSet<String>();
			for(int j = 0; j < documents[i].length; j++) termsets[i].add(documents[i][j]);
		}


	}

	/**
	 * Test method for {@link coms6111.astbbw.webdb.DocumentSample#addPages(coms6111.astbbw.ResultSet)}.
	 */
	@Test
	public final void testAddPages() {
		ResultSet rs = new ResultSet(6);
		ResultSet rs_short = new ResultSet(2);
		ResultSet rs_childonly = new ResultSet(2);

		for (int i = 0; i < rs.getNodeLen(); i++) {
			rs.doc[i].URL = "page " + i;
			rs.doc[i].clickURL = "clickURL for page " + i;
		}
		int offset = rs.getNodeLen();
		for (int i = 0; i < rs_short.getNodeLen(); i++) {
			rs_short.doc[i].URL = "page " + (i + offset);
			rs_short.doc[i].clickURL = "clickURL for page " + (i + offset);
		}
		offset += rs_short.getNodeLen();
		for (int i = 0; i < rs_childonly.getNodeLen(); i++) {
			rs_childonly.doc[i].URL = "page " + (i + offset);
			rs_childonly.doc[i].clickURL = "clickURL for page " + (i + offset);
		}
		p.addPages(rs);
		Hashtable h = p.exposeLinkHash();
		Hashtable ch = c.exposeLinkHash();
		assertEquals(h.size(),4);
		p.addPages(rs_short);
		assertEquals(h.size(),6);
		c.addPages(rs_short);
		assertEquals(ch.size(),2);
		c.addPages(rs_childonly);
		assertEquals(ch.size(),4);

		int pShouldHave[] = { 0, 1 , 2, 3, 6, 7  };
		int cShouldHave[] = { 6, 7, 8, 9 };
		for (int i = 0; i < pShouldHave.length; i++) {
			String key = "page " + pShouldHave[i];
			String value = "clickURL for " + key;
			assertTrue(h.containsKey(key));
			assertEquals(h.get(key),value);
		}
		for (int i = 0; i < cShouldHave.length; i++) {
			String key = "page " + cShouldHave[i];
			String value = "clickURL for " + key;
			assertTrue(ch.containsKey(key));
			assertEquals(ch.get(key),value);
		}
	}

	/**
	 * Test method for {@link coms6111.astbbw.webdb.DocumentSample#updateAll()}.
	 */
	@Test
	public final void testUpdateAll() {
		try {
			p.updateAll();
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			fail("Failed");
		}
		assertEquals(p.exposeTermsHash().size(),6);
		assertEquals(c.exposeTermsHash().size(),2);
	}

	/**
	 * Test method for {@link coms6111.astbbw.webdb.DocumentSample#hasTermsFor(java.lang.String)}.
	 */
	@Test
	public final void testHasTermsFor() {
		//p.exposeTermsHash().put("page 1", new TreeSet<String>());
		assertFalse(p.expose_hasTermsFor("no such page"));
		assertTrue(p.expose_hasTermsFor("page 1"));
		assertTrue(c.expose_hasTermsFor("page 1"));
		assertFalse(p.expose_hasTermsFor("clickURL for page 1"));
		//c.exposeTermsHash().put("page 8", new TreeSet<String>());
		assertTrue(c.expose_hasTermsFor("page 8"));
		assertFalse(p.expose_hasTermsFor("page 8"));
		// may as well do the job right...
	}

	/**
	 * Test method for {@link coms6111.astbbw.webdb.DocumentSample#getTermsFor(java.lang.String)}.
	 */
	@Test
	public final void testGetTermsFor() {
		assertTrue(p.expose_getTermsFor("page 1").equals(termsets[1]));
		assertTrue(c.expose_getTermsFor("page 1").equals(termsets[1]));
		assertFalse(c.exposeTermsHash().containsKey("page 1"));
		assertTrue(c.expose_getTermsFor("page 7").equals(termsets[7]));
	}


	/**
	 * Test method for {@link coms6111.astbbw.webdb.DocumentSample#getDocumentFrequencies()}.
	 */
	@Test
	public final void testGetDocumentFrequencies() {
		TreeMap<String,Integer> cdf = c.getDocumentFrequencies();
		TreeMap<String,Integer> pdf = p.getDocumentFrequencies();
		assertEquals(1,pdf.get("repeat"));
		int pDocs[] = { 0,1,2,3,6,7,8,9};
		int cDocs[] = { 6,7,8,9};
		for (int i = 0; i < pDocs.length; i++)
			assertEquals(1,pdf.get("page" + pDocs[i] + "only"));
		for (int i = 0; i < cDocs.length; i++)
			assertEquals(1,cdf.get("page" + cDocs[i] + "only"));
		assertNull(cdf.get("repeat"));
		assertNull(cdf.get("page0only"));
		assertNull(pdf.get("page4only"));
		//fail("Not yet implemented"); // TODO
		assertEquals(2,pdf.get("parent and child"));
		assertEquals(1,cdf.get("parent and child"));
		assertEquals(8,pdf.get("everywhere"));
		assertEquals(4,cdf.get("everywhere"));
		try {
			TestableDocumentSample.printSample(pdf, "test_output.txt");
		} catch (java.io.IOException e) {
			System.err.println(e.getMessage());
		}
	}



	static class TestableDocumentSample extends DocumentSample {
		protected static int WAIT_MILLISECS = 0;
		public TestableDocumentSample(){super();}
		public TestableDocumentSample(TestableDocumentSample p){super(p);}
		public Hashtable<String,String> exposeLinkHash() {
			return this.pageLinks;
		}
		public Hashtable<String,Set<String>> exposeTermsHash() {
			return this.pageTerms;
		}
		public boolean expose_hasTermsFor(String pageURL) {
			return this.hasTermsFor(pageURL);
		}
		public Set<String> expose_getTermsFor(String pageURL) {
			return this.getTermsFor(pageURL);
		}
		protected boolean updatePage(String pageURL) {
			if ( this.hasTermsFor(pageURL) ) return false;
			int i = Integer.parseInt(pageURL.substring(5) );
			Set<String> terms = termsets[i];
			pageTerms.put(pageURL, terms);
			return false;
		}

	}
}
